package com.motu.monstercity.server.game.logic;

import com.motu.monstercity.module.common.network.ResponseUtils;
import com.motu.monstercity.module.common.utility.Constant;
import com.motu.monstercity.module.common.utility.EventBusConstant;
import com.motu.monstercity.protocol.Common;
import com.motu.monstercity.protocol.Common.PBUserData;
import com.motu.monstercity.protocol.CsGameSystem;
import com.motu.monstercity.server.game.base.AllParam;
import com.motu.monstercity.server.game.base.CommonUtils;
import com.motu.monstercity.server.game.base.ProtoDataUtils;
import com.motu.monstercity.server.game.commondata.bag.ItemId;
import com.motu.monstercity.server.game.commondata.build.*;
import com.motu.monstercity.server.game.commondata.iap.PrivilegeCardConstant;
import com.motu.monstercity.server.game.commondata.maintask.MainTaskConstant;
import com.motu.monstercity.server.game.commondata.maintask.TaskAchieve;
import com.motu.monstercity.server.game.commondata.partner.PartnerConstant;
import com.motu.monstercity.server.game.commondata.system.SystemConstant;
import com.motu.monstercity.server.game.commondata.system.UserExp;
import com.motu.monstercity.server.game.commondata.world.WorldRadar;
import com.motu.monstercity.server.game.log.LogType;
import com.motu.monstercity.server.game.log.MotuLogManager;
import com.motu.monstercity.server.game.userdata.*;
import com.motu.vertx.module.utility.main.MainService;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class BuildManager extends BuildUserData {
    // 初始化 下发建筑模块的用户数据
    public static void loadInitBuildUserData(PBUserData.Builder pbUserData, UserInfo userInfo, List<UserBuild> userBuildList, boolean isNoLoadAll) {
        long userId = userInfo.getId();
        UserSoldierRecover userSoldierRecover = getUserSoldierRecover(userId);
        ProtoDataUtils.updatePBUserData(pbUserData, userSoldierRecover, true);

        UserCityInfo userCityInfo = getUserCityInfo(userId);
		ProtoDataUtils.updatePBUserData(pbUserData, userCityInfo, true);

        for (UserBuild userBuild : getUserBuildList(userId)) {
            BuildMain buildMain = getBuildMain(userBuild.getBuildId());
            if (buildMain == null) {
                userBuild.delete();// 删除脏数据
            } else {
                userBuildList.add(userBuild);
                ProtoDataUtils.updatePBUserData(pbUserData, userBuild, true);// 下发给客户端

                if (buildMain.isCityCenter()) {// 全量更新都市等级的任务进度，后台设置账号等级没同步更新任务进度
                    MainTaskManager.updateTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_113, userBuild.getLevel());// 更新主线任务,成就,日常任务的进度
                }
            }
        }

        if (!isNoLoadAll) {
            // 下发坐标列表
            for (UserCityCoord userCityCoord : getUserCityCoordList(userId)) {
                if (userCityCoord.getItemId() == 0) {
                    userCityCoord.delete();
                } else {
                    ProtoDataUtils.updatePBUserData(pbUserData, userCityCoord, true);
                }
            }

            // 下发地方方块用户信息列表
            for (UserBuildTile userBuildTile : getUserBuildTileList(userId)) {
                ProtoDataUtils.updatePBUserData(pbUserData, userBuildTile, true);
            }
        }
    }

    /**
     * 写入玩家的初始地面信息
     * @param userId
     * @param jsonArray 忽略列表,已拆除或是已经移动
     */
    public static void loadUserCityCoord(long userId, JsonArray jsonArray) {
        for (BuildInitCoord buildInitCoord : getBuildInitCoordMap().values()) {
            long crood = buildInitCoord.getCrood();
            if (!Tool.isInList(jsonArray, crood)) {
                UserCityCoord userCityCoord = new UserCityCoord(userId, buildInitCoord.getCrood(), buildInitCoord.getBuildId(), buildInitCoord.getIsTurn(), "", TimeUtils.getCurTime());
                userCityCoord.doCreate();
            }
        }
    }

    // 根据x,y,z生成唯一的坐标1zzxxxxyyyy 共13位
    public static long takeCoord(int x, int y, int z) {
        String xx = CommonUtils.numberToString(x, 4);
        String yy = CommonUtils.numberToString(y, 4);
        String zz = CommonUtils.numberToString(z, 2);
        return Long.parseLong("1" + zz + xx + yy);
    }

    // 1zzxxxxyyyy 从这个取坐标x,y,z
    public static int takeCoordXYZ(long coord, String type) {
        String str = String.valueOf(coord);
        int result = 0;
        try {
            String zz = str.substring(1,3);
            String xx = str.substring(3,7);
            String yy = str.substring(7,11);
            if (type.equals("X")) {
                result = Integer.parseInt(xx);
            } else if (type.equals("Y")) {
                result = Integer.parseInt(yy);
            } else if (type.equals("Z")) {
                result = Integer.parseInt(zz);
            }
        } catch (Exception e) {
        }
        return result;
    }

    // 判断这个建筑是否可以解锁 关卡,主角等级,人口数量,全部达标才可以解锁
    public static boolean isCanUnlock(BuildMain buildMain, UserInfo userInfo) {
        if (buildMain.getUnlockStage() > 0) {// 关卡是否达标
            UserStage userStage = FightManager.getUserStage(userInfo.getId());
            if (userStage == null || userStage.getMapId() < buildMain.getUnlockStage()) {
                return false;
            }
        }
        if (buildMain.getUnlockLevel() > 0 && userInfo.getLevel() < buildMain.getUnlockLevel()) {
            return false;// 主角等级不达标
        }
        if (buildMain.getUnlockPeason() > 0) {// 人口数量（居民+流浪汉) 是否达标
            UserCityInfo userCityInfo = getUserCityInfo(userInfo.getId());
            if (userCityInfo.getPeasonNum() < buildMain.getUnlockPeason()) {
                return false;
            }
        }
        return true;
    }

    // 市政中心是否可以升级
    public static boolean isCityCenterLevelUp(UserInfo userInfo, UserExp userExp) {
        if (Tool.isEmpty(userExp.getNeedTask()) || userExp.getNeedTask().equals("0")) {
            return true;
        }

        JsonArray jsonArray = CommonUtils.strToJsonArray(userExp.getNeedTask());
        for (int i=0; i<jsonArray.size(); i++) {
            int taskAchieveId = jsonArray.getInteger(i);
            TaskAchieve taskAchieve = MainTaskManager.getTaskAchieve(taskAchieveId);
            if (!MainTaskManager.isTaskComplete(userInfo.getId(), taskAchieve)) {
                return false;
            }
        }
        return true;
    }

    // 获得装饰类建筑logParams 获得后是已经解锁的状态，由玩家自己进行摆放
    public static void addRewardBuild(UserInfo userInfo, int itemId, PBUserData.Builder pbUserData, Object... logParams) {
        long userId = userInfo.getId();
        BuildMain buildMain = getBuildMain(itemId);
        if (buildMain == null) {
            return;
        }
        UserBuild userBuild = getUserBuild(userId, itemId);
        if (userBuild == null) {
            int isUnlock = 1;// 直接解锁
            userBuild = new UserBuild(userId, itemId, 1, isUnlock);
            userBuild.doCreate();
            MotuLogManager.logItemIncome(userInfo, itemId, 0, 0, 1, logParams);// 记录获得日志
            ProtoDataUtils.updatePBUserData(pbUserData, userBuild, true);
        } else {
        }
    }

    // 扣除装饰类建筑
    public static void subRewardBuild(UserInfo userInfo, int itemId, PBUserData.Builder pbUserData, Object... logParams) {
//        long userId = userInfo.getId();
//        BuildMain buildMain = getBuildMain(itemId);
//        if (buildMain == null || !buildMain.isDecorateBuild()) {// 只有装饰类建筑可以扣除数量
//            return;
//        }
//        UserBuild userBuild = getUserBuild(userId, itemId);
//        userBuild.subNum(userInfo, 1, logParams);
    }

    /**
     * 结算到当前时间的城市收益有多少 临时收益=（建筑收益+后代收益）*（1+特权卡收益加成+永久收益加成+临时收益加成）
     * @param pbUserData
     * @param userInfo
     * @param userPower
     * @param userAffair
     * @param isOffLine 是离线收益还是挂机收益
     * @return
     */
    public static long countTotalEarnNow(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, UserAffair userAffair, boolean isOffLine) {
        long userId = userInfo.getId();
        long totalEarn = userPower.getEarn();// 当前的总收益
        long curTime = TimeUtils.getCurTime();
        long diffTime = TimeUtils.getTimeDiff(userAffair.getEarnTime());// 收益的时间
        if (diffTime < 0) {
            return 0L;
        }
        long maxTime = (AllParam.EARN_TIME_MAX + IapManager.takePrivilegeValueByType(userId, PrivilegeCardConstant.TYPE_OFF_TIME_ADD_NUM)) * TimeUtils.HOUR;// 离线收益的上限时间
        diffTime = Math.min(diffTime, maxTime);// 不能超过上限
        long totalNum = totalEarn * diffTime;// 获得金币数量
        String logParam = totalEarn + "_t:" + diffTime;// 消耗获得日志备注
        int logType = isOffLine ? LogType.BUILD_EARN_OFFLINE : LogType.BUILD_EARN_AFK;// 日志类型
        RewardManager.addReward(userInfo, ItemId.GOLD, totalNum, pbUserData, logType, logParam);
        if (isOffLine && totalNum > 0) {// 把离线收益的金币数量记录下来，观看广告再领取一遍
            userAffair.putOfflineGoldNum(totalNum);
        }
        userAffair.putEarnTime(curTime);
        userAffair.update();
        ProtoDataUtils.updatePBUserData(pbUserData, userAffair);
        return totalNum;
    }


    // 统计所有商业建筑里派遣干员的总数量
    public static int countPartnerNum(long userId) {
        List<UserBuild> buildList  = getUserBuildList(userId);
        int total = 0;
        for (UserBuild userBuild : buildList)  {
            BuildMain buildMain = getBuildMain(userBuild.getBuildId());
            if (buildMain.isBusinessBuild())  {
                total += userBuild.getPartnerArray().size();
            }
        }
        return total;
    }

    // 统计商业建筑的总等级
    public static int countBusinessBuildLevel(long userId) {
        List<UserBuild> buildList = getUserBuildListByType(userId, BuildConstant.BUILD_TYPE_2);// 所有商业建筑
        int total = 0;
        for (UserBuild userBuild : buildList)  {
            BuildMain buildMain = getBuildMain(userBuild.getBuildId());
            if (buildMain.isBusinessBuild() && userBuild.isPlace())  {
                total += userBuild.getLevel();
            }
        }
        return total;
    }

    // {0}间商铺达到{1}级（0：x间建筑）
    public static void updateMainTaskNum(PBUserData.Builder pbUserData, UserInfo userInfo) {
        long userId = userInfo.getId();
        List<UserBuild> buildList = getUserBuildListByType(userId, BuildConstant.BUILD_TYPE_2);
        for (TaskAchieve taskAchieve : MainTaskManager.getTaskAchieveMapByTaskType(MainTaskConstant.TASK_TYPE_123).values()) {
            int minLevel = taskAchieve.getParam();
            int num = countBuildNumByLevel(buildList, minLevel);// >level 的建筑有多少
            MainTaskManager.updateTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_123, num, minLevel);// 更新主线任务,成就,日常任务的进度
        }
//        ActDaysManager.updatBuildTask(userInfo, pbUserData, buildList);
        ActDaysManager.updateOuterTask(userInfo, pbUserData, MainTaskConstant.TASK_TYPE_123, buildList, BuildManager::countBuildNumByLevel);
        RankActManager.updateCrossOuterTask(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_123, buildList, BuildManager::countBuildNumByLevel);
        ActConventionManager.updateOuterTask(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_123, buildList, BuildManager::countBuildNumByLevel);
    }

    // >level 的建筑有多少
    public static int countBuildNumByLevel(List<UserBuild> buildList, int minLevel) {
        int count = 0;
        for (UserBuild userBuild : buildList) {
            if (userBuild.getLevel() - 1 >= minLevel) {
                count++;
            }
        }
        return count;
    }

    // 银行的加成
    public static int takeBankAddEarn(UserBuild userBuild) {
        if (userBuild == null) {
            return 0;// 银行为解锁
        }
        BuildMain buildMain = getBuildMain(userBuild.getBuildId());
        if (buildMain == null || !buildMain.isBuildBank()) {
            return 0;
        }
        BuildBank buildBank = BuildManager.getBuildBank(userBuild.getLevel());
        if (buildBank == null) {
            return 0;
        }
        return buildBank.getEarnSpeedAdd();
    }

    // 银行的升级会影响各个商业建筑的城市收益
    public static void handleBankLevelUp(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, UserBuild userBuildBank) {
        int newValue = takeBankAddEarn(userBuildBank);// 加成值
        if (newValue != userPower.getEarnAddBankPer()) {
            userPower.putEarnAddBankPer(newValue);
            List<UserBuild> buildList = userPower.takeUserBuildList(0);// 所有商业建筑的收益都会提升
            BuildManager.batchUpdateBuildEarn(pbUserData, userInfo, userPower, buildList);
        }
    }

    // 地标建筑解锁，对相应性格的商业建筑有加成
    public static void handleBuildUnlock(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, BuildMain buildMain) {
        if (!buildMain.isDecorateBuild() || buildMain.getEffectValue() == 0) {
            return;
        }
        // 增量更新  技能加成值数组[100,200,300,400,500,600]
        int charType = buildMain.getEffectType();// 地标建筑对哪个性格的商业建筑有加成，配置在effecttype
        JsonArray jsonArray = SkillManager.addSkillEffectArray(charType, buildMain.getEffectValue(), userPower.getEarnAddDecoratePerArray());
        userPower.putEarnAddDecoratePer(jsonArray.toString());
        List<UserBuild> buildList = userPower.takeUserBuildList(charType);// 对应的商业建筑
        BuildManager.batchUpdateBuildEarn(pbUserData, userInfo, userPower, buildList);// 批量更新商业建筑的城市收益，并更新userpower下发给客户端
    }



    // 清除坐标信息,并下发给客户端
    public static void clearUserCityCoord(PBUserData.Builder pbUserData, UserCityCoord  userCityCoord) {
        if (userCityCoord == null)  {
            return;
        }
        userCityCoord.putItemId(0);// 把itemid 改成0
        userCityCoord.putParam("");
        userCityCoord.putIsTurn(0);
        userCityCoord.putBuildTime(0);
        userCityCoord.update();
        ProtoDataUtils.deletePBUserData(pbUserData, userCityCoord);// 客户端item_id=0就不显示对应建筑的信息
    }

    // 生成坐标信息,并下发给客户端
    public static void creatUserCityCoord(PBUserData.Builder pbUserData, UserCityCoord  userCityCoord, long userId, long coord, int buildId, int isTurn, String param, long buildTime) {
        if (userCityCoord == null) {
            userCityCoord = new UserCityCoord(userId, coord, buildId, isTurn, param, buildTime);
            userCityCoord.doCreate();
        } else {
            userCityCoord.putItemId(buildId);
            userCityCoord.putIsTurn(isTurn);
            userCityCoord.putParam(param);
            userCityCoord.putBuildTime(buildTime);
            userCityCoord.update();
        }
        ProtoDataUtils.updatePBUserData(pbUserData, userCityCoord, true);// 原来可能是item_id=0的,初始化没下发给客户端
    }

    // 判断这个建筑是否可以摆放
    public static boolean checkBuildCanPlace(BuildMain buildMain, UserBuild userBuild)  {
        if (buildMain.isDefaultUnlock()) {
            return true;// 默认解锁的建筑,可以直接摆放
        }
        if (userBuild != null && userBuild.isUnlock()) {
            return true;// 已经解锁
        } else {
            return false;// 不能摆放
        }
    }

    // 获取拆除列表里面的初始地图的坐标列表
    public static JsonArray getInitCoordList(JsonArray keyList, ConcurrentHashMap<Long, UserCityCoord> userCityCoordList) {
        JsonArray jsonArray = new JsonArray();
        for (int i=0;i<keyList.size();i++) {
            long coord = keyList.getLong(i);
            if (!userCityCoordList.containsKey(coord))  {
                jsonArray.add(coord);
            }
        }
        return jsonArray;
    }

    // 通知gameinit 进程,异步生成初始地图的数据
    public static void noticeLoadInitCoord(long userId, JsonArray jsonArray) {
        JsonObject message = new JsonObject();
        message.put("userId", userId);
        message.put("clearList", jsonArray);
        message.put("loadInitCoord", true);//
        String ebName = EventBusConstant.getAddress(EventBusConstant.GAME_INIT);
        EventBus eventBus = MainService.getVertx().eventBus();
        eventBus.send(ebName, message);
    }

    // 城市总人口上限
    public static int getCityPeasonMax(UserInfo userInfo) {
        UserExp userExp = GameDataManager.getUserExp(userInfo.getLevel());
        if (userExp == null) {
            return 0;
        } else {
            return userExp.getPeasonLimit();
        }
    }


    // 医院治疗伤兵需要消耗多少时间
    public static long countRecoverSoldierTime(int recoverValue, int num) {
        double total = (double) num / recoverValue;
        return (long) Math.ceil(total);// 向上取整
    }

    //  医院治疗伤员，实际的恢复速度，每秒恢复多少人
    public static int getRecoverValue(long userId, BuildHospital buildHospital) {
        int priAdd = IapManager.takePrivilegeValueByType(userId, PrivilegeCardConstant.TYPE_HOSPITAL_RECOVER_VALUE);// 特权卡加成
        int recoveValue = buildHospital.getRecoverValue() + priAdd;// 每秒恢复多少人
        return recoveValue;
    }

    // 快速治疗需要消耗的钻石数量
    public static long getRecoverQuickItemNum(long costTime) {
        double total = (double) costTime / AllParam.HOSPITAL_QUICK_TIME_COST;
        return (long) Math.ceil(total);// 向上取整
    }

    // 是否可发起医院治疗求助
    public static boolean isCanSeekHelpSoldierRecover(UserSoldierRecover userSoldierRecover) {
        if (!userSoldierRecover.isRecovering()) { // 当前不是治疗中
            return false;
        }

        if (userSoldierRecover.getEndTime() < TimeUtils.getCurTime()) { // 当前治疗已经结束
            return false;
        }
        if (userSoldierRecover.getHelpDbid() > 0) {
            return false;// 已经发起过了
        }

        return true;
    }

    // 对行军进行助力，增加扣除的时间，并推送给发起求助的玩家
    public static void handleDoHelp(long userId, String uniqeId, int reduceTime, UserInfo userInfoFrom, UnionReciprocityList unionReciprocityList) {
        UserSoldierRecover userSoldierRecover = getUserSoldierRecover(userId);
        if (!userSoldierRecover.getUniqeId().equals(uniqeId)) {
            return;
        }
        userSoldierRecover.addReduceTime(reduceTime);
        userSoldierRecover.update();

        CsGameSystem.CSGameSystemPushDataResponse.Builder response = CsGameSystem.CSGameSystemPushDataResponse.newBuilder();
        Common.PBUserData.Builder pbUserData = response.getUserBuilder();
        ProtoDataUtils.updatePBUserData(pbUserData, userSoldierRecover);

        response.setType(ResponseUtils.PUSH_TIPS_TYPE_2);
        response.setUserId(userInfoFrom.getId());
        response.setUserName(userInfoFrom.getUserName());
        response.addParam(unionReciprocityList.getHelpNum() + "");
        response.addParam(unionReciprocityList.getHelpNumMax() + "");

        JsonObject jsonObject = ResponseUtils.getPushResponseData(response.build().toByteArray());// 广播给其他人的数据
        GameUser.pushToUser(userId, jsonObject);
    }

    /**
     * 装饰类建筑对建筑的收益的加成，目前只有type =4 6 的才会有加成
     * @return jsonarray格式的字符串，固定6个值CHARACTER_TYPE_SIZE + 1，第一个表示所有性格，第二个表示性格1
     */
    public static String getEarnAddDecorate(List<UserBuild> userBuildList) {
        JsonArray jsonArray = SkillManager.createSkillEffectArray();
        int value0 = 0;
        int value1 = 0;
        int value2 = 0;
        int value3 = 0;
        int value4 = 0;
        int value5 = 0;
        for (UserBuild userBuild : userBuildList) {
            BuildMain buildMain = getBuildMain(userBuild.getBuildId());
            if (buildMain == null) {
                continue;
            }
            if (buildMain.isDecorateBuild() && userBuild.isUnlock()) {
                if (buildMain.getEffectType() == 0) {
                    value0 += buildMain.getEffectValue();
                } else if (buildMain.getEffectType() == Constant.CHARACTER_TYPE_1) {
                    value1 += buildMain.getEffectValue();
                } else if (buildMain.getEffectType() == Constant.CHARACTER_TYPE_2) {
                    value2 += buildMain.getEffectValue();
                } else if (buildMain.getEffectType() == Constant.CHARACTER_TYPE_3) {
                    value3 += buildMain.getEffectValue();
                } else if (buildMain.getEffectType() == Constant.CHARACTER_TYPE_4) {
                    value4 += buildMain.getEffectValue();
                } else if (buildMain.getEffectType() == Constant.CHARACTER_TYPE_5) {
                    value5 += buildMain.getEffectValue();
                }
            }
        }
        jsonArray.set(0, value0);
        jsonArray.set(Constant.CHARACTER_TYPE_1, value1);
        jsonArray.set(Constant.CHARACTER_TYPE_2, value2);
        jsonArray.set(Constant.CHARACTER_TYPE_3, value3);
        jsonArray.set(Constant.CHARACTER_TYPE_4, value4);
        jsonArray.set(Constant.CHARACTER_TYPE_5, value5);

        return jsonArray.toString();
    }

    /**
     * 计算伤兵治疗总的需要消耗的道具
     * @param type 治疗类型。慢速治疗 快速治疗等
     * @param num 治疗人数
     * @return
     */
    public static List<RewardItem> countSoldierRecoverItem(int type, int num) {
        BuildHospital buildHospital = BuildManager.getBuildHospital(type);
        List<RewardItem> rewardItemList = CommonUtils.takeReawrdItemFromStr(buildHospital.getRecoverCost());// 恢复伤员需要消耗的钻石
        CommonUtils.multipleItemList(rewardItemList, num);
        return rewardItemList;
    }

    // 获取所有的商业建筑Id 列表
    public static JsonArray getBuildIds(List<UserBuild> userBuildList) {
        JsonArray jsonArray = new JsonArray();
        for (UserBuild userBuild : userBuildList) {
            int buildId = userBuild.getBuildId();
            if (userBuild.isBusinessBuild() && userBuild.isPlace() && !Tool.isInList(jsonArray, buildId)) {
                jsonArray.add(buildId);
            }
        }
        return jsonArray;
    }

    /**
     * 批量更新商业建筑的城市收益，并更新userpower下发给客户端
     * @param pbUserData
     * @param userInfo
     * @param userPower
     * @param buildList 商业建筑列表
     */
    public static void batchUpdateBuildEarn(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, List<UserBuild> buildList) {
        long totalAdd = 0L;
        if (buildList != null && buildList.size() > 0) {
            for (UserBuild userBuild : buildList) {
                long addValue = userBuild.reCountEarn(userInfo, userPower);
                if (addValue != 0) {
                    userBuild.update();
                    ProtoDataUtils.updatePBUserData(pbUserData, userBuild);
                }
                //System.out.println("buildid:" + userBuild.getBuildId() + " addvalue:" + addValue);
                totalAdd += addValue;
            }
        }
        if (totalAdd != 0) {
            userPower.addBuildEarn(pbUserData, userInfo, totalAdd);
        } else {
            userPower.update();
            ProtoDataUtils.updatePBUserData(pbUserData, userPower);
        }
    }
}
